package org.mozhu.demo.dynamodb.lowlevel;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.model.*;
import org.mozhu.demo.dynamodb.DynamoFactory;

public class LowLevelTableExample {

    String tableName = "ExampleTable";
    AmazonDynamoDB client = DynamoFactory.getDynamoInstance();

    public void createTable() {
        ProvisionedThroughput provisionedThroughput = new ProvisionedThroughput()
                .withReadCapacityUnits(5L)
                .withWriteCapacityUnits(6L);

        CreateTableRequest createTableRequest = new CreateTableRequest()
                .withTableName(tableName)
                .withAttributeDefinitions(new AttributeDefinition().withAttributeName("Id").withAttributeType("N"))
                .withKeySchema(new KeySchemaElement().withAttributeName("Id").withKeyType(KeyType.HASH))
                .withProvisionedThroughput(provisionedThroughput);
        client.createTable(createTableRequest);

        waitForTableToBecomeAvailable();
        getTableInformation();
    }

    public void updateExampleTable() {
        ProvisionedThroughput provisionedThroughput = new ProvisionedThroughput()
                .withReadCapacityUnits(6L)
                .withWriteCapacityUnits(7L);

        UpdateTableRequest updateTableRequest = new UpdateTableRequest()
                .withTableName(tableName)
                .withProvisionedThroughput(provisionedThroughput);

        client.updateTable(updateTableRequest);
        waitForTableToBecomeAvailable();
    }

    public void getTableInformation() {
        TableDescription tableDescription = client.describeTable(
                new DescribeTableRequest().withTableName(tableName)).getTable();
        System.out.format("Name: %s:\n" +
                        "Status: %s \n" +
                        "Provisioned Throughput (read capacity units/sec): %d \n" +
                        "Provisioned Throughput (write capacity units/sec): %d \n",
                tableDescription.getTableName(),
                tableDescription.getTableStatus(),
                tableDescription.getProvisionedThroughput().getReadCapacityUnits(),
                tableDescription.getProvisionedThroughput().getWriteCapacityUnits());
    }

    private void waitForTableToBecomeAvailable() {
        System.out.println("Waiting for " + tableName + " to become ACTIVE...");

        long startTime = System.currentTimeMillis();
        long endTime = startTime + (10 * 60 * 1000);
        while (System.currentTimeMillis() < endTime) {
            DescribeTableRequest request = new DescribeTableRequest()
                    .withTableName(tableName);
            TableDescription tableDescription = client.describeTable(
                    request).getTable();
            String tableStatus = tableDescription.getTableStatus();
            System.out.println("  - current state: " + tableStatus);
            if (tableStatus.equals(TableStatus.ACTIVE.toString()))
                return;
            try {
                Thread.sleep(1000 * 5);
            } catch (Exception e) {
            }
        }
        throw new RuntimeException("Table " + tableName + " never went active");
    }


    public void deleteExampleTable() {
        DeleteTableRequest deleteTableRequest = new DeleteTableRequest()
                .withTableName(tableName);
        client.deleteTable(deleteTableRequest);
        waitForTableToBeDeleted();
    }

    private void waitForTableToBeDeleted() {
        System.out.println("Waiting for " + tableName + " while status DELETING...");

        long startTime = System.currentTimeMillis();
        long endTime = startTime + (10 * 60 * 1000);
        while (System.currentTimeMillis() < endTime) {
            try {
                DescribeTableRequest request = new DescribeTableRequest().withTableName(tableName);
                TableDescription tableDescription = client.describeTable(request).getTable();
                String tableStatus = tableDescription.getTableStatus();
                System.out.println("  - current state: " + tableStatus);
                if (tableStatus.equals(TableStatus.ACTIVE.toString())) return;
            } catch (ResourceNotFoundException e) {
                System.out.println("Table " + tableName + " is not found. It was deleted.");
                return;
            }
            try {
                Thread.sleep(1000 * 5);
            } catch (Exception e) {
            }
        }
        throw new RuntimeException("Table " + tableName + " was never deleted");
    }


    public void listMyTables() {
        String lastEvaluatedTableName = null;
        do {
            ListTablesRequest listTablesRequest = new ListTablesRequest()
                    .withLimit(10)
                    .withExclusiveStartTableName(lastEvaluatedTableName);

            ListTablesResult result = client.listTables(listTablesRequest);
            lastEvaluatedTableName = result.getLastEvaluatedTableName();

            for (String name : result.getTableNames()) {
                System.out.println(name);
            }

        } while (lastEvaluatedTableName != null);
    }
}
